/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#pragma once

#include <math.h>
#include "基本类型.h"
#include "基础量.h"
#include "SIMD/CPU_向量计算.h"

#include "basic_vec.h"




template<typename T1, typename T2>
CUDA_CALLABLE inline void vec4_cpy(T1& v1, const T2& v2) {
	v1.x = v2.x; v1.y = v2.y; v1.z = v2.z; v1.w = v2.w;
}
template<typename T1, typename T2>
CUDA_CALLABLE inline void vec3_cpy(T1& v1, const T2& v2) {
	v1.x = v2.x; v1.y = v2.y; v1.z = v2.z;
}

template<typename T1, typename T2>
CUDA_CALLABLE inline void vec2_cpy(T1& v1, const T2& v2) {
	v1.x = v2.x; v1.y = v2.y; 
}

template<typename T1, typename T2>
CUDA_CALLABLE inline void vec2_set(T1& v1, const T2& v2) {
	v1.x = v2; v1.y = v2;
}






inline void vec3_填充(float32* vec, const float32 填充数) {
	vec[0] = 填充数; vec[1] = 填充数; vec[2] = 填充数;
}
inline void vec3_填充(vec3* vec, const float32 填充数) {
	vec->x = 填充数; vec->y = 填充数; vec->z = 填充数;
}
//inline void vec3_填充(vec3* vec, const float32* 填充数) {
//	vec->x = 填充数[0]; vec->y = 填充数[1]; vec->z = 填充数[2];
//}
inline void vec3_填充(vec3* vec, const float32 x, const float32 y, const float32 z) {
	vec->x = x; vec->y = y; vec->z = z;
}
inline void vec3_填充(vec3* vec, const vec3* 填充数) {
	vec->x = 填充数->x; vec->y = 填充数->y; vec->z = 填充数->z;
}
inline void vec3_填充(vec3* vec, const vec4* 填充数) {
	vec->x = 填充数->x; vec->y = 填充数->y; vec->z = 填充数->z;
}
inline void vec4_填充(vec4* vec, const float32 填充数) {
	vec->x = 填充数; vec->y = 填充数; vec->z = 填充数; vec->w = 填充数;
}
inline void vec4_填充(vec4* vec, const float32* 填充数) {
	vec->x = 填充数[0]; vec->y = 填充数[1]; vec->z = 填充数[2]; vec->w = 填充数[3];
}
inline void vec4_填充(vec4* vec, const vec4* 填充数) {
	vec->x = 填充数->x; vec->y = 填充数->y; vec->z = 填充数->z; vec->w = 填充数->w;
}
inline void vec4_填充(vec4* vec, const vec3* 填充数, const float32 value = 1.0f) {
	vec->x = 填充数->x; vec->y = 填充数->y; vec->z = 填充数->z; vec->w = value;
}
inline void vec4_copy(vec4* vec, const vec3& 填充数) {
	vec->x = 填充数.x; vec->y = 填充数.y; vec->z = 填充数.z; 
}
inline void vec4_填充(vec4* vec, float32 x, float32 y, float32 z, float32 w) {
	vec->x = x; vec->y = y; vec->z = z; vec->w = w;
}

inline void vec_填充(vec3* vec, const vec4& 填充数) {
	vec->x = 填充数.x; vec->y = 填充数.y; vec->z = 填充数.z;
}
inline void vec_fill(vec3* vec, const vec3& 填充数) {
	vec->x = 填充数.x; vec->y = 填充数.y; vec->z = 填充数.z;
}
inline void vec_fill(vec4* vec, const vec3& 填充数) {
	vec->x = 填充数.x; vec->y = 填充数.y; vec->z = 填充数.z;
}

inline void vec_填充(vec4* vec, const float32 填充数) {
	vec->x = 填充数; vec->y = 填充数; vec->z = 填充数; vec->w = 填充数;
}



inline void ui3_32_填充(uvec3* vec, const uvec3* 填充数) {
	vec->x = 填充数->x; vec->y = 填充数->y; vec->z = 填充数->z;
}
inline void ui3_32_填充(uvec3* vec, const uint32* 填充数) {
	vec->x = 填充数[0]; vec->y = 填充数[1]; vec->z = 填充数[2];
}







inline bool f_比较(const uvec4& v1, const uvec4& v2) {
	if (v1.x == v2.x && v1.y == v2.y && v1.z == v2.z && v1.w == v2.w) return true;
	return false;
}









/************************** 类型转换 *************************/

inline void vec_转换(ivec3* t, const vec3* s) {
	t->x = s->x; t->y = s->y; t->z = s->z;
}
inline void vec_转换(vec3* t, const ivec3* s) {
	t->x = s->x; t->y = s->y; t->z = s->z;
}
inline void vec_转换(uvec3* t, const ivec3* s) {
	t->x = s->x; t->y = s->y; t->z = s->z;
}
inline void vec_转换(uvec3* t, const vec3* s) {
	t->x = s->x; t->y = s->y; t->z = s->z;
}
inline void vec_转换(vec3* t, const vec4& s) {
	t->x = s.x; t->y = s.y; t->z = s.z;
}

inline vec4 vec_转换(const vec3& vec, const float32 填充数) {
	return { vec.x, vec.y, vec.z, 填充数 };
}

inline vec4 vec_3转4(const vec3& vec, const float32 填充数) {
	return { vec.x, vec.y, vec.z, 填充数 };
}
inline vec3 vec_4转3(const vec4& vec) {
	return { vec.x, vec.y, vec.z };
}

inline vec3 vec_转换(const uvec3& vec) {
	return { float32(vec.x), float32(vec.y), float32(vec.z) };
}
inline ivec3 vec_转换i(const vec3& vec) {
	return { int32(vec.x), int32(vec.y), int32(vec.z) };
}
inline uvec3 vec_转换(const vec3& vec) {
	return { uint32(vec.x), uint32(vec.y), uint32(vec.z) };
}
Inline uvec4 ivec_1转4(const uint32 vec) {
	return { uint32(vec), uint32(vec), uint32(vec), 1 };
}
inline uvec3 ivec_4转3(const uvec4& vec) {
	return { uint32(vec.x), uint32(vec.y), uint32(vec.z) };
}
Inline uvec4 ivec_3转4(const uvec3& vec) {
	return { uint32(vec.x), uint32(vec.y), uint32(vec.z), 1 };
}
Inline uvec2 vec_f3转u2(const vec3& vec) {
	return { uint32(vec.x), uint32(vec.y) };
}









//计算向量长度
CUDA_CALLABLE Inline float64 vec_len(const float vec[3]){
	return sqrt( fabs( (vec[0]*vec[0]) + (vec[1]*vec[1]) + (vec[2]*vec[2]) ) );
}

CUDA_CALLABLE Inline float32 vec_len(const vec4& vec) {
	return sqrt(fabs((vec.x * vec.x) + (vec.y * vec.y) + (vec.z * vec.z) ));
	//return sqrt(fabs((vec.x * vec.x) + (vec.y * vec.y) + (vec.z * vec.z) + (vec.w * vec.w)));
}
CUDA_CALLABLE Inline float32 vec_len(const vec2& vec) {
	return sqrt( fabs((vec.x * vec.x) + (vec.y * vec.y)) );
}

Inline float32 vec_len(const vec3& vec) {
	return sqrt(fabs((vec.x * vec.x) + (vec.y * vec.y) + (vec.z * vec.z)));
}
Inline float32 vec3_len(const vec3& vec) {
	return sqrt(fabs((vec.x * vec.x) + (vec.y * vec.y) + (vec.z * vec.z)));
}

Inline float32 length(const vec2& vec) {
	return sqrt(fabs((vec.x * vec.x) + (vec.y * vec.y)));
}

/*inline float32 vec_len(const vec3 vec0, const vec3 vec1) {
	return vec_len(vec_dis(vec1, vec0));
}*/




CUDA_CALLABLE inline vec3 vec3_角度转弧度(const vec3& 角度) {
	return { float32(M_角度转弧度(角度.x)), float32(M_角度转弧度(角度.y)), float32(M_角度转弧度(角度.z)) };
}

CUDA_CALLABLE inline vec3 vec3_弧度转角度(const vec3& 角度) {
	return { float32(M_弧度转角度(角度.x)), float32(M_弧度转角度(角度.y)), float32(M_弧度转角度(角度.z)) };
}
CUDA_CALLABLE inline vec3 vec3_弧度转角度360(const vec3& 角度) {
	return { float32(M_弧度转360角度(角度.x)), float32(M_弧度转360角度(角度.y)), float32(M_弧度转360角度(角度.z)) };
}

CUDA_CALLABLE inline vec3 f_欧拉角度转弧度(vec3 a) {
	return { float32(M_360角度转弧度(a.x)), float32(M_360角度转弧度(a.y)), float32(M_360角度转弧度(a.z)) };
}



//倒置
CUDA_CALLABLE inline void 向量_反转(float vec[3]){
	vec[0] = -vec[0]; vec[1] = -vec[1]; vec[2] = -vec[2];
}
CUDA_CALLABLE inline void vec_反向(vec3* vec) {
	vec->x = -vec->x; vec->y = -vec->y; vec->z = -vec->z;
}
CUDA_CALLABLE inline vec3 vec_反向(const vec3& vec) {
	return { -vec.x, -vec.y, -vec.z };
}
CUDA_CALLABLE inline vec3 vec_取反(const vec3& vec) {
	return{ -vec.x, -vec.y, -vec.z };
}





//两点间距离
CUDA_CALLABLE inline float 向量_两向量距离(const float vec0[3], const float vec1[3]){
	return (float32)sqrt(
			fabs( (vec1[0] - vec0[0]) * (vec1[0] - vec0[0])
			+ (vec1[1] - vec0[1]) * (vec1[1] - vec0[1])
			+ (vec1[2] - vec0[2]) * (vec1[2] - vec0[2])
			)
		);
}
CUDA_CALLABLE inline float 向量_两向量距离(const float vec[3]){
	return (float32)sqrt( fabs(vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2]) );
}

//归一化向量
CUDA_CALLABLE inline float32 f_normalize(const float32 v, const float32 min, const float32 max) { return v / (max - min); }
CUDA_CALLABLE inline float vec_归一化(float vec[3]){
	float len = (float)vec_len(vec);

	vec[0] /= len; vec[1] /= len; vec[2] /= len;
	//qDebug()<<"len =vec[2]= "<<vec[2];
	return len;
}
/*CUDA_CALLABLE inline float vec_normalize(vec3& vec) {
	float len = (float)vec_len(vec);
	if (len) {
		vec.x /= len; vec.y /= len; vec.z /= len;
		return len;
	}
	else return 0.0f;
}*/
inline vec2 normalize(const vec2& vec) {
	float32 len = (float32)vec_len(vec) + DEF_浮点精度补充;
	return { vec.x / len, vec.y / len };
}
Inline vec3 normalize(const vec3& vec) {
	float len = (float)vec_len(vec);
	if (len) {
		return { vec.x / len, vec.y / len, vec.z / len };
	}
	else return {};
}


CUDA_CALLABLE inline vec3 vec_normalize(const vec3& vec) {
	float len = (float)vec_len(vec);
	if (len) {
		return { vec.x / len, vec.y / len, vec.z / len };
	}
	else return {};
}

CUDA_CALLABLE inline vec2 vec_normalize2(const vec2& vec) {
	float32 len = (float32)vec_len(vec) + DEF_浮点精度补充;
	return { vec.x / len, vec.y / len };
}
CUDA_CALLABLE inline vec3 vec_normalize2(const vec3& vec) {
	float len = (float)vec_len(vec) + DEF_浮点精度补充;
	return { vec.x / len, vec.y / len, vec.z / len };
}

CUDA_CALLABLE inline float vec_normalize(vec3* vec) {
	float len = (float)vec_len(*vec) + DEF_浮点精度补充;
	if(len > 0) vec->x /= len; vec->y /= len; vec->z /= len;
	return len;
}
CUDA_CALLABLE inline float vec_normalize(vec4* vec) {
	float len = (float)vec_len(*vec);
	if (len > 0) {
		len = 1.0f / len;
		vec->x *= len; vec->y *= len; vec->z *= len; vec->w *= len;
	}
	else {
		(*vec) = {0,0,0,1};
	}
	return len;
}
CUDA_CALLABLE inline float32 vec_normalize(vec2* vec) {
	float32 len = (float32)vec_len(*vec);
	vec->x /= len; vec->y /= len; ;
	return len;
}
CUDA_CALLABLE inline vec2 vec_normalize(const vec2& vec) {
	float len = (float)vec_len(vec);
	return vec2{ vec.x / len, vec.y / len };
}
CUDA_CALLABLE inline float vec_归一化(const float vec[3], float normalizeVec[3]){
	float len = (float)vec_len(vec);
	normalizeVec[0] /= len; normalizeVec[1] /= len; normalizeVec[2] /= len;
	return len;
}

CUDA_CALLABLE inline float32 vec2_归一化(float32 向量[2]) {
	float 长度 = sqrt(fabs((向量[0] * 向量[0]) + (向量[1] * 向量[1])));
	向量[0] /= 长度; 向量[1] /= 长度;
	return 长度;
}
CUDA_CALLABLE inline float32 vec3_归一化(vec3* 向量) {
	float 长度 = sqrt(fabs((向量->x * 向量->x) + (向量->y * 向量->y) + (向量->z * 向量->z)));
	向量->x /= 长度; 向量->y /= 长度; 向量->z /= 长度;
	return 长度;
}

CUDA_CALLABLE inline float32 vec_dis(vec4 va, vec4 vb) {
	vec3 dis = { va.x - vb.x, va.y - vb.y , va.z - vb.z };
	return float32(vec_len((float32*)&dis));
}
CUDA_CALLABLE inline float32 vec_dis(const vec3& va, const vec3& vb) {
	vec3 dis = { va.x - vb.x, va.y - vb.y , va.z - vb.z };
	return float32(vec_len((float32*)&dis));
}
CUDA_CALLABLE inline float32 vec_dis(const vec3& va, const vec4& vb) {
	vec3 dis = { va.x - vb.x, va.y - vb.y , va.z - vb.z };
	return float32(vec_len((float32*)&dis));
}
CUDA_CALLABLE inline float32 vec_dis(vec4 va, vec3 vb) {
	vec3 dis = { va.x - vb.x, va.y - vb.y , va.z - vb.z };
	return float32(vec_len((float32*)&dis));
}









//向量相减
CUDA_CALLABLE inline void vec_相减(float 返回结果[3], const float* vec0, const float* vec1){
	返回结果[0] = vec0[0] - vec1[0];
	返回结果[1] = vec0[1] - vec1[1];
	返回结果[2] = vec0[2] - vec1[2];
}
CUDA_CALLABLE inline void vec_sub(vec3& 返回结果, const vec3& vec0, const vec3& vec1) {
	返回结果.x = vec0.x - vec1.x;
	返回结果.y = vec0.y - vec1.y;
	返回结果.z = vec0.z - vec1.z;
}
CUDA_CALLABLE inline void vec_sub(vec2* vec0, const vec2& vec1) {
	vec0->x -= vec1.x; 
	vec0->y -= vec1.y;
}
CUDA_CALLABLE inline vec2 vec_sub(const vec2& vec0, const vec2& vec1) {
	return { vec0.x - vec1.x, vec0.y - vec1.y };
}
CUDA_CALLABLE inline vec3 vec_sub(const vec3& vec0, const float vec1) {
	return vec0 - vec1;
}
CUDA_CALLABLE inline vec3 vec_sub(const vec3& vec0, const vec3& vec1) {
	return vec0 - vec1;
}
CUDA_CALLABLE inline vec3 vec_sub(const vec3& vec0, const ivec3& vec1) {
	return{ vec0.x - vec1.x, vec0.y - vec1.y, vec0.z - vec1.z };
}
CUDA_CALLABLE inline vec3 vec_sub(const vec3& vec0, const uvec3& vec1) {
	return{ vec0.x - vec1.x, vec0.y - vec1.y, vec0.z - vec1.z };
}
CUDA_CALLABLE inline void vec_sub(vec3* vec0, const vec3& vec1) {
	vec0->x -= vec1.x;
	vec0->y -= vec1.y;
	vec0->z -= vec1.z;
}
CUDA_CALLABLE inline void vec_sub(vec3* vec0, const float32 vec1) {
	vec0->x -= vec1;
	vec0->y -= vec1;
	vec0->z -= vec1;
}
CUDA_CALLABLE inline void vec2_相减(float 返回结果[2], const float* vec0, const float* vec1) {
	返回结果[0] = vec0[0] - vec1[0];
	返回结果[1] = vec0[1] - vec1[1];
}








//向量相加
CUDA_CALLABLE inline void vec_相加(float 返回向量[3], const float* vec0, const float* vec1){
	返回向量[0] = vec1[0] + vec0[0];
	返回向量[1] = vec1[1] + vec0[1];
	返回向量[2] = vec1[2] + vec0[2];
}
CUDA_CALLABLE inline void vec_自加(float vec[3], const float value){
	vec[0] += value;
	vec[1] += value;
	vec[2] += value;
}
CUDA_CALLABLE inline void vec_自加(float vec[3], const float 加速向量[3]) {
	vec[0] += 加速向量[0];
	vec[1] += 加速向量[1];
	vec[2] += 加速向量[2];
}

CUDA_CALLABLE inline void vec_相加(const vec3* vec加数, const vec3* vec被加数, vec3* vec结果) {
	vec结果->x = vec加数->x + vec被加数->x;
	vec结果->y = vec加数->y + vec被加数->y;
	vec结果->z = vec加数->z + vec被加数->z;
}
CUDA_CALLABLE inline void vec_自加(vec3* vec结果, const vec3* vec加数) {
	vec结果->x += vec加数->x;
	vec结果->y += vec加数->y;
	vec结果->z += vec加数->z;
}
CUDA_CALLABLE inline void vec_add(vec2* vec, const vec2& 加数向量) {
	vec->x += 加数向量.x; 
	vec->y += 加数向量.y;
}

									
Inline vec3 vec_add(const vec3& vec, const float32& 加数向量) {
	return vec + 加数向量;									
}															
Inline vec3 vec_add_3_1(const vec3& vec, const float32& 加数向量) {
	return vec + 加数向量;
}

Inline vec3 vec_add(const vec3& vec, const vec3& 加数向量) {
	return vec + 加数向量;
}
Inline vec3 vec_add_3_3(const vec3& vec, const vec3& 加数向量) {
	return vec + 加数向量;
}


CUDA_CALLABLE inline ivec3 vec_add(ivec3& vec, const float32& 加数向量) {
	return { int32(vec.x + 加数向量), int32(vec.y + 加数向量), int32(vec.z + 加数向量) };
}


CUDA_CALLABLE inline void vec_add(vec3* vec, const float32 s) {
	vec->x += s; vec->y += s; vec->z += s;
}


CUDA_CALLABLE inline void vec_add(vec3* vec, const vec3& 加数向量) {
	vec->x += 加数向量.x; vec->y += 加数向量.y; vec->z += 加数向量.z;
}

CUDA_CALLABLE inline vec3 vec_add(const vec3& vec, const uvec3& 加数向量) {
	return {
		vec.x + 加数向量.x,
		vec.y + 加数向量.y,
		vec.z + 加数向量.z
	};
}
CUDA_CALLABLE inline vec3 vec_add(const vec3& vec, const ivec3& 加数向量) {
	return {
		vec.x + 加数向量.x,
		vec.y + 加数向量.y,
		vec.z + 加数向量.z
	};
}

CUDA_CALLABLE inline void vec_add(vec4* vec, const vec3& 加数向量) {
	vec->x += 加数向量.x;
	vec->y += 加数向量.y;
	vec->z += 加数向量.z;
}
CUDA_CALLABLE inline vec4 vec_add(const vec4& vec, const vec3& 加数向量) {
	return { vec.x + 加数向量.x, vec.y + 加数向量.y, vec.z + 加数向量.z, vec.w };
}

CUDA_CALLABLE inline void vec_add(vec3* vec, const vec4& 加数向量) {
	vec->x += 加数向量.x;
	vec->y += 加数向量.y;
	vec->z += 加数向量.z;
}



CUDA_CALLABLE inline void vec_mul(vec2* vec, const float value) {
	vec->x *= value;
	vec->y *= value;
}
CUDA_CALLABLE inline void vec_mul(vec3* vec, const float value) {
	vec->x *= value;
	vec->y *= value;
	vec->z *= value;
}
CUDA_CALLABLE inline void vec_mul(vec3* vec, const vec3& value) {
	vec->x *= value.x;
	vec->y *= value.y;
	vec->z *= value.z;
}

CUDA_CALLABLE inline void vec_自乘(vec3* vec, const vec3* 乘数) {
	vec->x *= 乘数->x;
	vec->y *= 乘数->y;
	vec->z *= 乘数->z;
}
CUDA_CALLABLE Inline void vec_自乘(vec3* vec, const vec3& 乘数) {
	vec->x *= 乘数.x;
	vec->y *= 乘数.y;
	vec->z *= 乘数.z;
}
CUDA_CALLABLE inline void vec_自乘(vec3* vec, const float 乘数) {
	vec->x *= 乘数;
	vec->y *= 乘数;
	vec->z *= 乘数;
}
CUDA_CALLABLE inline void vec_自乘(float vec[3], const float value){
	vec[0] *= value;
	vec[1] *= value;
	vec[2] *= value;
}


CUDA_CALLABLE inline void vec_mul(vec2* vec, const vec2& value) {
	vec->x *= value.x; vec->y *= value.y;
}
CUDA_CALLABLE inline vec2 vec_mul(const vec2& vec, const vec2& value) {
	return { vec.x * value.x, vec.y * value.y };
}
CUDA_CALLABLE inline vec2 vec_mul(const vec2& vec, const float value) {
	return { vec.x * value, vec.y * value };
}

Inline vec3 vec_mul(const vec3& 结果, const float value) {
	return 结果 * value;
}
Inline vec3 vec_multi_3_1(const vec3& 结果, const float value) {
	return 结果 * value;
}

Inline vec3 vec_mul(const vec3& vec, const vec3& value) {
	return vec * value;
}
Inline vec3 vec_multi_3_3(const vec3& vec, const vec3& value) {
	return vec * value;
}


CUDA_CALLABLE inline vec3 vec_mul(const vec3& vec, const ivec3& value) {
	return { vec.x * value.x, vec.y * value.y, vec.z * value.z };
}
CUDA_CALLABLE inline vec3 vec_mul(const vec3& vec, const uvec3& value) {
	return { vec.x * value.x, vec.y * value.y, vec.z * value.z };
}


Inline vec4 vec_mul(const vec4& vec, const float32 value) {
	return vec * value;
}


//CUDA_CALLABLE inline void vec_multi(vec3* vec, const vec3 value) {
//	vec->x* value.x,  vec->y* value.y, vec->z * value.z;
//}




CUDA_CALLABLE inline void vec_相乘(const float vec[3], const float value, float vec1[3]){
	vec1[0] = vec[0] * value;
	vec1[1] = vec[1] * value;
	vec1[2] = vec[2] * value;
}
CUDA_CALLABLE inline void vec_相乘(const vec3* vec, const float value, vec3* 结果) {
	结果->x = vec->x * value;
	结果->y = vec->y * value;
	结果->z = vec->z * value;
}
CUDA_CALLABLE inline void vec_mul(vec3& 结果, const vec3& vec, const float value) {
	结果.x = vec.x * value;
	结果.y = vec.y * value;
	结果.z = vec.z * value;
}
CUDA_CALLABLE inline void vec_mul(vec4* 结果, const float value) {
	结果->x *= value;
	结果->y *= value;
	结果->z *= value;
}
CUDA_CALLABLE inline void vec_mul(vec4* 结果, const vec4& value) {
	结果->x *= value.x;
	结果->y *= value.y;
	结果->z *= value.z;
}
CUDA_CALLABLE inline void vec_mul(vec4& 结果, const vec3& vec, const float value) {
	结果.x = vec.x * value;
	结果.y = vec.y * value;
	结果.z = vec.z * value;
}



CUDA_CALLABLE inline vec2 vec_div(const vec2& vec, const vec2& value) {
	return { vec.x / value.x, vec.y / value.y};
}
CUDA_CALLABLE inline vec3 vec_div(const vec3& vec, const float32 value) {
	return vec / value;
}
CUDA_CALLABLE inline vec3 vec_div(const vec3& vec, const vec3& value) {
	return vec / value;
}
CUDA_CALLABLE inline vec3 vec_div(const vec3& vec, const ivec3& value) {
	return { vec.x / value.x, vec.y / value.y, vec.z / value.z };
}
CUDA_CALLABLE inline vec3 vec_div(const vec3& vec, const uvec3& value) {
	return { vec.x / value.x, vec.y / value.y, vec.z / value.z };
}
CUDA_CALLABLE inline vec3 vec_div(const float value, const vec3& vec) {
	return { value / vec.x , value / vec.y, value / vec.z};
}
CUDA_CALLABLE inline void vec_自除(float vec[3], const float value){
	vec[0] /= value;
	vec[1] /= value;
	vec[2] /= value;
}
CUDA_CALLABLE inline void vec_相除(const float vec[3], const float value, float vec1[3]){
	vec1[0] = vec[0] / value;
	vec1[1] = vec[1] / value;
	vec1[2] = vec[2] / value;
}
CUDA_CALLABLE inline vec3 vec_除(const vec3 vec, const float value) {
	return { vec.x / value, vec.y / value, vec.z / value };
}
CUDA_CALLABLE inline void vec_div(vec3* vec, const float32 value) {
	vec->x /= value; vec->y /= value; vec->z /= value;
}
CUDA_CALLABLE inline void vec_div(vec3* vec, const vec3& value) {
	vec->x /= value.x; vec->y /= value.y; vec->z /= value.z;
}





//向量点积
CUDA_CALLABLE inline float vec_dot(const float* vec0, const float* vec1){
	return vec0[0] * vec1[0] + vec0[1] * vec1[1] + vec0[2] * vec1[2];
}
CUDA_CALLABLE inline float vec_dot(const vec3& vec0, const vec3& vec1) {
	return vec0.x * vec1.x + vec0.y * vec1.y + vec0.z * vec1.z;
}
CUDA_CALLABLE inline float vec_dot(const vec4& vec0, const vec3& vec1) {
	return vec0.x * vec1.x + vec0.y * vec1.y + vec0.z * vec1.z ;
}
CUDA_CALLABLE inline float vec_dot(const vec2& vec0, const vec2& vec1) {
	return vec0.x * vec1.x + vec0.y * vec1.y;
}


Inline float dot(const vec2& vec0, const vec2& vec1) {
	return vec0.x * vec1.x + vec0.y * vec1.y;
}
Inline float dot(const vec3& vec0, const vec3& vec1) {
	return vec0.x * vec1.x + vec0.y * vec1.y + vec0.z * vec1.z;
}


//向量叉积
CUDA_CALLABLE inline void vec_叉积(float* vec2, const float* vec0, const float* vec1){
	//a × b = [a2*b3 ? a3*b2, a3*b1 ? a1*b3, a1*b2 ? a2*b1]
	vec2[0] = vec0[1]*vec1[2] - vec0[2]*vec1[1];
	vec2[1] = vec0[2]*vec1[0] - vec0[0]*vec1[2];
	vec2[2] = vec0[0]*vec1[1] - vec0[1]*vec1[0];
}
CUDA_CALLABLE inline vec3 vec_cross(const vec2& vec0, const vec2& vec1) {
	return { vec0.y * 0 - 0 * vec1.y,
			0 * vec1.x - vec0.x * 0,
			vec0.x * vec1.y - vec0.y * vec1.x };
}
CUDA_CALLABLE inline vec3 vec_cross(const vec3& vec0, const vec3& vec1) {
	//a × b = [a2*b3 ? a3*b2, a3*b1 ? a1*b3, a1*b2 ? a2*b1]
	return { vec0.y * vec1.z - vec0.z * vec1.y,
			vec0.z * vec1.x - vec0.x * vec1.z,
			vec0.x * vec1.y - vec0.y * vec1.x };
}
CUDA_CALLABLE inline vec3 vec_cross(const vec4& vec0, const vec3& vec1) {
	//a × b = [a2*b3 ? a3*b2, a3*b1 ? a1*b3, a1*b2 ? a2*b1]
	return { vec0.y * vec1.z - vec0.z * vec1.y,
			vec0.z * vec1.x - vec0.x * vec1.z,
			vec0.x * vec1.y - vec0.y * vec1.x };
}

CUDA_CALLABLE inline vec3 cross(const vec2& vec0, const vec2& vec1) {
	return { vec0.y * 0 - 0 * vec1.y,
			0 * vec1.x - vec0.x * 0,
			vec0.x * vec1.y - vec0.y * vec1.x };
}
Inline vec3 cross(const vec3& vec0, const vec3& vec1) {
	return { vec0.y * vec1.z - vec0.z * vec1.y,
			vec0.z * vec1.x - vec0.x * vec1.z,
			vec0.x * vec1.y - vec0.y * vec1.x };
}












CUDA_CALLABLE inline vec3 vec_step(const vec3& vec0, const vec3& vec1) {
	return { float32(int32(vec0.x / vec1.x)), float32(int32(vec0.y / vec1.y)), float32(int32(vec0.z / vec1.z)) };
}


CUDA_CALLABLE inline vec3 vec_mix(const vec3& A, const vec3& B, const float value) {
	//return { A.x * value + B.x * (1.0f - value), A.y * value + B.y * (1.0f - value), A.z * value + B.z * (1.0f - value) };
	return { B.x * value + A.x * (1.0f - value), B.y * value + A.y * (1.0f - value), B.z * value + A.z * (1.0f - value) };
	//return { A.x * value + B.x * (1.0f-value), A.y * value + B.y * (1.0f - value), A.z * value + B.z * (1.0f - value) };
}










CUDA_CALLABLE inline vec2 vec_Max(const vec2& v1, const vec2& v2) {
	return { DEF_Max(v1.x, v2.x), DEF_Max(v1.y, v2.y) };
}
CUDA_CALLABLE inline vec2 vec_Min(const vec2& v1, const vec2& v2) {
	return { DEF_Min(v1.x, v2.x), DEF_Min(v1.y, v2.y) };
}

CUDA_CALLABLE inline vec3 vec_Max(const vec3& v1, const vec3& v2) {
	return { DEF_Max(v1.x, v2.x), DEF_Max(v1.y, v2.y), DEF_Max(v1.z, v2.z) };
}
CUDA_CALLABLE inline vec3 vec_Min(const vec3& v1, const vec3& v2) {
	return { DEF_Min(v1.x, v2.x), DEF_Min(v1.y, v2.y), DEF_Min(v1.z, v2.z) };
}

CUDA_CALLABLE inline uvec3 vec_Max(const uvec3& v1, const uvec3& v2) {
	return { DEF_Max(v1.x, v2.x), DEF_Max(v1.y, v2.y), DEF_Max(v1.z, v2.z) };
}
CUDA_CALLABLE inline uvec3 vec_Min(const uvec3& v1, const uvec3& v2) {
	return { DEF_Min(v1.x, v2.x), DEF_Min(v1.y, v2.y), DEF_Min(v1.z, v2.z) };
}

Inline float32 vec_Max(const vec3& v) {
	return DEF_Max(DEF_Max(v.x, v.y), v.z);
}




CUDA_CALLABLE inline uvec4 vec_转uv4(const uvec3& v) {
	return { v.x, v.y, v.z, 1 };
}







//**************************************************************************//
//                             向量合并
//**************************************************************************//

CUDA_CALLABLE inline vec4 vec_合并(const vec2& v1, const vec2& v2) {
	return { v1.x, v1.y, v2.x, v2.y };
}






/****************************************************************************/
//                                 转换
/****************************************************************************/
inline ivec2 f_vec(uvec2 v) { return { int32(v.x), int32(v.y) }; }
inline vec2 f_vec_F(ivec2 v) { return { float32(v.x), float32(v.y) }; }
inline vec2 f_vec_F(uvec2 v) { return { float32(v.x), float32(v.y) }; }

inline uvec2 f_vec_UI(vec2 v) { return { uint32(v.x), uint32(v.y) }; }
inline uvec2 f_vec_UI(ivec2 v) { return { uint32(v.x), uint32(v.y) }; }

inline S_RGBA8UI f_rgb_to_rgba(S_RGB8UI v) { return { uint8(v.r), uint8(v.g), uint8(v.b), 255 }; }







/*inline vec2 vec_cross(vec2& vec0, const vec2& vec1) {
	//a × b = [a2*b3 ? a3*b2, a3*b1 ? a1*b3, a1*b2 ? a2*b1]
	return { vec0.x * vec1.y - vec1.x * vec0.y,
		vec0.z * vec1.x - vec0.x * vec1.z,
		vec0.x * vec1.y - vec0.y * vec1.x };
}*/
Inline vec2 vec_abs(const vec2& v) {
	return {fabs(v.x), fabs(v.y)};
}
Inline vec3 vec_abs(const vec3& v) {
	return { fabs(v.x), fabs(v.y), fabs(v.z) };
}


Inline float vec_mag2(vec3 v) {
	return vec_dot(v, v);
}
Inline vec3 f_vec_normalizDiv(vec3 v, float32 s) {
	return vec_mul(v, 1.0f / s);
}


inline bool f_equal(const uvec4& vecA, const uvec4& vecB) {
	if (vecA.x == vecB.x && vecA.y == vecB.y && vecA.z == vecB.z) {
		return true;
	}
	return false;
}



CUDA_CALLABLE inline void Vector_Reflect(float vecR[3], const float vecI[3], const float vecN[3]){
	//vecR = vecI - 2(vecI*vecN)vecN;
	//v' = v - 2 * (v*N) *N
	vecR[0] = vecN[0]; vecR[1] = vecN[1]; vecR[2] = vecN[2];
	vec_自乘(vecR, vec_dot(vecI, vecN));
	vec_自乘(vecR, 2.0f);
	vec_相减(vecR, vecI, vecR);
}

CUDA_CALLABLE inline void Vector_Reflect(float vecR[3], const float vecI[3], const float vecN[3], float* rate){
	//vecR = vecI - 2(vecI*vecN)vecN;
	//v' = v - 2 * (v*N) *N
	*rate = vec_dot(vecI, vecN);
	vecR[0] = vecN[0]; vecR[1] = vecN[1]; vecR[2] = vecN[2];
	vec_自乘(vecR, *rate);
	vec_自乘(vecR, 2);
	vec_相减(vecR, vecI, vecR);
}





CUDA_CALLABLE inline float64 getRotateAngle(vec2& v1, vec2& v2, float32 A = 180.0)
{
	const double epsilon = 1.0e-6;
	const double nyPI = acos(-1.0);
	double dist, dot, degree, angle;

	// normalize
	dist = vec_normalize(&v1);
	dist = vec_normalize(&v2);

	// dot product
	dot = vec_dot(v1, v2);
	if (fabs(dot - 1.0) <= epsilon)
		angle = 0.0;
	else if (fabs(dot + 1.0) <= epsilon)
		angle = nyPI;
	else {
		double cross;

		angle = acos(dot);
		//cross product
		cross = v1.x * v2.y - v2.x * v1.y;
		// vector p2 is clockwise from vector p1
		// with respect to the origin (0.0)
		if (cross < 0) {
			angle = 2 * nyPI - angle;
		}
	}
	degree = angle * A / nyPI;
	return degree;
}

CUDA_CALLABLE inline float64 getRotateAngle(const vec2& v1) {
	vec2 v = v1;
	//vec_normalize(&v);

	float32 dx = vec_dot({ 0,1 }, v);
	//float32 dy = vec_dot({ 1,0 }, v);

	//第一象限
	if (v.x >= 0 && v.y >= 0) {
		return dx * 90.0;
	}
	//第二象限
	if (v.x < 0 && v.y >= 0) {
		return (1.0 - dx) * 90.0 + 90.0;
	}
	//第三象限
	if (v.x < 0 && v.y < 0) {
		return (-dx) * 90.0 + 180.0;
	}
	//第四象限
	if (v.x >= 0 && v.y < 0) {
		return (1+dx) * 90.0 + 270.0;
	}

	return 0.0;
}





CUDA_CALLABLE inline float32 f_get向量夹角(const vec3& v1, const vec3& v2) {
	return vec_dot(v1, v2) / (vec_len(v1) * vec_len(v2));
}
CUDA_CALLABLE inline float64 get两向量Angle(const vec2& v1, const vec2& v2) {
	float64 角度1 = getRotateAngle(v1);
	float64 角度2 = getRotateAngle(v2);
	return 角度1 - 角度2;
}










inline vec3 f_svec3(svec3& v) {
	return { float32(v.x), float32(v.y), float32(v.z) };
}







//沿向量旋转
inline void vec_沿向量旋转(float resultDir[3], const float vecR[3], const float RotationDir[3], const float angle) {
	/** 计算 sin 和cos值 */
	float cosTheta = (float)cos(M_角度转弧度(angle));
	float sinTheta = (float)sin(M_角度转弧度(angle));

	/** 计算旋转向量的x值 */
	resultDir[0] = (cosTheta + (1 - cosTheta) * RotationDir[0] * RotationDir[0]) * vecR[0];
	resultDir[0] += ((1 - cosTheta) * RotationDir[0] * RotationDir[1] - RotationDir[2] * sinTheta) * vecR[1];
	resultDir[0] += ((1 - cosTheta) * RotationDir[0] * RotationDir[2] + RotationDir[0] * sinTheta) * vecR[2];

	/** 计算旋转向量的y值 */
	resultDir[1] = ((1 - cosTheta) * RotationDir[0] * RotationDir[1] + RotationDir[2] * sinTheta) * vecR[0];
	resultDir[1] += (cosTheta + (1 - cosTheta) * RotationDir[1] * RotationDir[1]) * vecR[1];
	resultDir[1] += ((1 - cosTheta) * RotationDir[1] * RotationDir[2] - RotationDir[0] * sinTheta) * vecR[2];

	/** 计算旋转向量的z值 */
	resultDir[2] = ((1 - cosTheta) * RotationDir[0] * RotationDir[2] - RotationDir[1] * sinTheta) * vecR[0];
	resultDir[2] += ((1 - cosTheta) * RotationDir[1] * RotationDir[2] + RotationDir[0] * sinTheta) * vecR[1];
	resultDir[2] += (cosTheta + (1 - cosTheta) * RotationDir[2] * RotationDir[2]) * vecR[2];

}
inline vec3 vec_沿向量旋转(const vec3& vecR, const vec3& RotationDir, const float angle) {
	vec3 resultDir;

	/** 计算 sin 和cos值 */
	float cosTheta = (float)cos(M_角度转弧度(angle));
	float sinTheta = (float)sin(M_角度转弧度(angle));

	/** 计算旋转向量的x值 */
	resultDir.x = (cosTheta + (1 - cosTheta) * RotationDir.x * RotationDir.x) * vecR.x;
	resultDir.x += ((1 - cosTheta) * RotationDir.x * RotationDir.y - RotationDir.z * sinTheta) * vecR.y;
	resultDir.x += ((1 - cosTheta) * RotationDir.x * RotationDir.z + RotationDir.x * sinTheta) * vecR.z;

	/** 计算旋转向量的y值 */
	resultDir.y = ((1 - cosTheta) * RotationDir.x * RotationDir.y + RotationDir.z * sinTheta) * vecR.x;
	resultDir.y += (cosTheta + (1 - cosTheta) * RotationDir.y * RotationDir.y) * vecR.y;
	resultDir.y += ((1 - cosTheta) * RotationDir.y * RotationDir.z - RotationDir.z * sinTheta) * vecR.z;

	/** 计算旋转向量的z值 */
	resultDir.z = ((1 - cosTheta) * RotationDir.x * RotationDir.z - RotationDir.y * sinTheta) * vecR.x;
	resultDir.z += ((1 - cosTheta) * RotationDir.y * RotationDir.z + RotationDir.x * sinTheta) * vecR.y;
	resultDir.z += (cosTheta + (1 - cosTheta) * RotationDir.z * RotationDir.z) * vecR.z;

	return resultDir;
}




inline char get_line_intersection(float p0_x, float p0_y, float p1_x, float p1_y,
	float p2_x, float p2_y, float p3_x, float p3_y, float* i_x, float* i_y)
{
	float s1_x, s1_y, s2_x, s2_y;
	s1_x = p1_x - p0_x;     s1_y = p1_y - p0_y;
	s2_x = p3_x - p2_x;     s2_y = p3_y - p2_y;

	float s, t;
	s = (-s1_y * (p0_x - p2_x) + s1_x * (p0_y - p2_y)) / (-s2_x * s1_y + s1_x * s2_y);
	t = (s2_x * (p0_y - p2_y) - s2_y * (p0_x - p2_x)) / (-s2_x * s1_y + s1_x * s2_y);

	if (s >= 0 && s <= 1 && t >= 0 && t <= 1)
	{
		// Collision detected
		if (i_x != NULL)
			*i_x = p0_x + (t * s1_x);
		if (i_y != NULL)
			*i_y = p0_y + (t * s1_y);
		return 1;
	}

	return 0; // No collision
}



inline int get_line_intersection2(float p0_x, float p0_y, float p1_x, float p1_y,
	float p2_x, float p2_y, float p3_x, float p3_y, float* i_x, float* i_y)
{
	float s02_x, s02_y, s10_x, s10_y, s32_x, s32_y, s_numer, t_numer, denom, t;
	s10_x = p1_x - p0_x;
	s10_y = p1_y - p0_y;
	s32_x = p3_x - p2_x;
	s32_y = p3_y - p2_y;

	denom = s10_x * s32_y - s32_x * s10_y;
	if (denom == 0)
		return 0; // Collinear
	bool denomPositive = denom > 0;

	s02_x = p0_x - p2_x;
	s02_y = p0_y - p2_y;
	s_numer = s10_x * s02_y - s10_y * s02_x;
	if ((s_numer < 0) == denomPositive)
		return 0; // No collision

	t_numer = s32_x * s02_y - s32_y * s02_x;
	if ((t_numer < 0) == denomPositive)
		return 0; // No collision

	if (((s_numer > denom) == denomPositive) || ((t_numer > denom) == denomPositive))
		return 0; // No collision
				  // Collision detected
	t = t_numer / denom;
	if (i_x != NULL)
		*i_x = p0_x + (t * s10_x);
	if (i_y != NULL)
		*i_y = p0_y + (t * s10_y);

	return 1;
}





/********************************************************************************/
//									数据打包
/********************************************************************************/

inline uint64 f_PackData(const svec3& data) {
	return uint64(data.x) | uint64(data.y) << 16 | uint64(data.z) << 32 | uint64(0x00) << 48;
}
inline uint64 f_PackData4X64(const usvec4& data) {
	return uint64(data.x) | uint64(data.y) << 16 | uint64(data.z) << 32 | uint64(data.w) << 48;
}
inline uint64 f_PackData3X64(const uvec3& data) {
	return uint64(data.x) | uint64(data.y) << 21 | uint64(data.z) << 42;
}
inline uint64 f_PackData3X64(const ivec3& data) {
	return uint64(data.x + 1048575) | uint64(data.y + 1048575) << 21 | uint64(data.z + 1048575) << 42;
}


CUDA_CALLABLE inline uint32 f_PackData3X32f(const ivec3& data) {
	return uint32(data.x + 511) | (uint32(data.y + 511) << 10) | (uint32(data.z + 511) << 20);
}
CUDA_CALLABLE inline uint32 f_PackData3X32f(const svec3& data) {
	return uint32(data.x + 511) | (uint32(data.y + 511) << 10) | (uint32(data.z + 511) << 20);
}
CUDA_CALLABLE inline uint32 f_PackData3X32f(const vec3& data) {
	return uint32(data.x + 511) | (uint32(data.y + 511) << 10) | (uint32(data.z + 511) << 20);
}
inline uint16 f_PackData3X16(const vec3& data) {
	return uint16(data.x + 63) | (uint16(data.y + 63) << 6) | (uint16(data.z + 63) << 12);
}
inline uint16 f_PackData3X16(const svec3& data) {
	return uint16(data.x + 63) | (uint16(data.y + 63) << 6) | (uint16(data.z + 63) << 12);
}

inline uint32 f_PackData4X8(const S_RGBA8UI& data) {
	return (uint32(data.r) << 24 | (uint32(data.g) << 16) | (uint32(data.b) << 8) | uint32(data.a));
}



inline svec3 f_UpPackData3X32s(const uint32 data) {
	return { int16(data & 0b00000000000000000000001111111111) - 511
			,(int16((data >> 10) & 0b00000000000000000000001111111111) - 511)
			,(int16((data >> 20) & 0b00000000000000000000001111111111) - 511)
	};
}

inline ivec3 f_UpPackData3X64(const uint64 data) {
	return { int32((data & 0b0000000000000000000000000000000000000000000111111111111111111111)) - 1048575
			,(int32( ((data >> 21) & 0b0000000000000000000000000000000000000000000111111111111111111111)) - 1048575)
			,(int32( ((data >> 42) & 0b0000000000000000000000000000000000000000000111111111111111111111)) - 1048575)
	};
}



Inline uint32 f_hashIndex(const uvec3& data) {
	return ( (uint32)((data.x * 73856093) ^ (data.y * 19349669) ^ (data.z * 83492791)) );
}









typedef enum {
	e_欧拉, e_矩阵
}E_变换类型;

typedef struct {
	vec3 location;
	vec3 rotation;
	vec3 scale;
}S_Tranform; typedef S_Tranform* S_pTranform;

inline void f_TranformInit(S_Tranform& tranform) {
	tranform.location	= { 0.0f, 0.0f, 0.0f };
	tranform.rotation	= { 0.0f, 0.0f, 0.0f };
	tranform.scale		= { 1.0f,  1.0f, 1.0f };
}





//============================= 废弃 ================================
inline vec3 vec_转换v3(const vec4& vec) {
	return { vec.x, vec.y, vec.z };
}

